
//***************************************************************************************************
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "tree_t.h"
#include "defines.h"
//***************************************************************************************************

//***************************************************************************************************
extern unsigned Left_indent;
//***************************************************************************************************

//***************************************************************************************************
struct tree_elem_t *node_constructor (double info, char info_type)
{

    OUT ("# called node_constructor(/ %lg / -> ' %c ' || / %d /)\n", info, (char)info, info_type);
    assert (info_type >= 0); assert (info_type < 5);

    struct tree_elem_t *new_node = (struct tree_elem_t*)calloc (1, sizeof (struct tree_elem_t));
    assert (new_node != NULL);

    new_node -> data.info_type = info_type;
    switch (info_type)
    {
        case INFO_TYPE_ACTION:
            new_node -> data.info = (char)(info);
            break;
        case INFO_TYPE_NUMBER:
            new_node -> data.info = info;
            break;
    }

    new_node -> link[0] = NULL;
    new_node -> link[1] = NULL;

    return new_node;
}
//***************************************************************************************************

//***************************************************************************************************
struct tree_elem_t *tree_clone (struct tree_elem_t *tree)
{
    assert (tree != NULL);
    OUT ("# called tree_clone([%p])\n", tree);
    Left_indent++;

    struct tree_elem_t *ret_value = NULL;

    ret_value = node_constructor ((double)tree->data.info, tree->data.info_type);

    if (tree->link[0] != NULL) ret_value->link[0] = tree_clone (tree->link[0]);
    if (tree->link[1] != NULL) ret_value->link[1] = tree_clone (tree->link[1]);

    Left_indent--;

    OUT ("# end tree_clone(); will return [%p]\n", ret_value);
    return ret_value;
}
//***************************************************************************************************

//***************************************************************************************************
void tree_destructor (struct tree_elem_t *tree)
{

    OUT ("# called tree_destructor([%p])\n", tree);
    assert (tree != NULL);

    if (tree -> link [0] != NULL) tree_destructor (tree -> link [0]);
    if (tree -> link [1] != NULL) tree_destructor (tree -> link [1]);

    tree -> link[0] = NULL;
    tree -> link[1] = NULL;

    tree -> data.info      = -666;
    tree -> data.info_type = 0;

    free (tree);
    tree = NULL;
}
//***************************************************************************************************

//***************************************************************************************************
void tree_print_tex (const struct tree_elem_t *tree, FILE *target_source)
{
    assert (tree != NULL);
    assert (target_source != NULL);

    if (tree->data.info_type == INFO_TYPE_NUMBER)
        fprintf (target_source, "%lg", (double)tree->data.info);
          else
            switch ((char)tree->data.info)
            {
                case '-':
                case '+':
                    fprintf (target_source, "(");
                    tree_print_tex (tree->link[0], target_source);
                    fprintf (target_source, "%c", (char)tree->data.info);
                    tree_print_tex (tree->link[1], target_source);
                    fprintf (target_source, ")");
                    return;
                case '*':
                    tree_print_tex (tree->link[0], target_source);
                    fprintf (target_source, "*");
                    tree_print_tex (tree->link[1], target_source);
                    return;
                case '/':
                    fprintf (target_source, "\\frac{");
                    tree_print_tex (tree->link[0], target_source);
                    fprintf (target_source, "}{");
                    tree_print_tex (tree->link[1], target_source);
                    fprintf (target_source, "}");
                    return;
                case 'S':
                    fprintf (target_source, "\\sin(");
                    tree_print_tex (tree->link[0], target_source);
                    fprintf (target_source, ")");
                    return;
                case 'C':
                    fprintf (target_source, "\\cos(");
                    tree_print_tex (tree->link[0], target_source);
                    fprintf (target_source, ")");
                    return;
                default:
                    if (tree->link[0] != NULL)
                    {
                        fprintf (target_source, "(");
                        tree_print_tex (tree->link[0], target_source);
                        fprintf (target_source, ")");
                    }
                    if (tree->data.info_type == INFO_TYPE_NUMBER)
                        fprintf (target_source, "%lg", (double)tree->data.info);   else
                            fprintf (target_source, "%c", (char)tree->data.info);
                    if (tree->link[1] != NULL)
                    {
                        fprintf (target_source, "(");
                        tree_print_tex (tree->link[1], target_source);
                        fprintf (target_source, ")");
                    }
                    return;
            }
}
//***************************************************************************************************
